package com.ruoyi.common.security.aspect;

import com.ruoyi.common.core.exception.auth.NotRepeatSubmitException;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.annotation.RepeatSubmit;
import com.ruoyi.common.security.auth.AuthUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

@Aspect
@Component
public class RepeatSubmitAspect {
    private static final String TOKEN_KEY="";

    @Autowired
    private RedisService redisService;

    public static final String POINTCUT_SIGN = " @annotation(com.ruoyi.common.security.annotation.RepeatSubmit) ";
    public RepeatSubmitAspect()
    {
    }
    @Pointcut(POINTCUT_SIGN)
    public void pointcut(){

    }

    /**
     * uuid的组装规则：path+token保证一个用户，一个接口，固定时间内，只能调用一次
     * 限流时间，作为redis key的过期时间。
     * 考虑两个请求并发到来的场景，可以用redislock加锁
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint)throws Throwable{
        MethodSignature signature=(MethodSignature) joinPoint.getSignature();

        RepeatSubmit repeatSubmit=signature.getMethod().getAnnotation(RepeatSubmit.class);
        if(repeatSubmit!=null){

            checkRepeat(repeatSubmit);
        }
        try {
            Object object=joinPoint.proceed();
            return object;
        }catch (Throwable e){
            throw e;
        }
    }

    public void checkRepeat(RepeatSubmit repeatSubmit){

        long lockTime=repeatSubmit.interval();
        String message=repeatSubmit.message();

        String key= AuthUtil.getKey(ServletUtils.getRequest());
        if(redisService.getCacheObject(key)!=null){
            throw new NotRepeatSubmitException(message);
        }

        redisService.setCacheObject(key,"1",lockTime, TimeUnit.SECONDS);

    }
}
